/**
 * Copyright &copy; 2012-2013 <a href="httparamMap://github.com/thinkgem/jeesite">JeeSite</a> All rights reserved.
 */
package com.server.modules.sys.service;

import java.math.BigDecimal;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import com.server.modules.sys.common.StaticDefine;
import com.server.modules.sys.dao.statistics.StatisticsDao;
import com.server.modules.sys.entity.Office;
import com.server.modules.sys.entity.User;
import com.server.modules.sys.utils.AmountUtils;
import com.server.modules.sys.utils.date.DateUtil;
import com.server.modules.sys.vo.statistics.TimeRangeParam;

/**
 * 
* @ClassName: StatisticsService 
* @Description: 统计service  非自动生成！ 
* @author dingGuangbiao 314667996@qq.com
* @date 2016-10-13 下午4:04:13
 */
@Service
@Transactional(readOnly = true)
public class StatisticsService   {
	@Resource
	private StatisticsDao dao;
	@Resource
	private OfficeService officeService;
	@Resource
	private SystemService systemService;
	/**
	 * @throws Exception 
	 * @throws ParseException 
	* @Title: getUserGrowthEchartsData 
	* @Description: 根据统计日期区间查询参数查询相对应日期类型的用户增长量echarts饼图统计数据
	* @author dingGuangbiao 314667996@qq.com
	* @date 2016-10-13 下午4:11:15 
	* @param @param 查询参数
	* @return Map<String,Object>   echarts饼图所需json 
	* @throws
	 */
	public Map<String,Object> getUserGrowthEchartsData(TimeRangeParam param) throws Exception{
		String rangeType = param.getRangeType();
		String officeOrUser = param.getOfficeOrUser();
		//如果是按部门查询的话  需要查询该部门下面的所有用户  然后sql里面用in（userid1，userid2..）搞定
		if(StaticDefine.STATISTICS_OFFICEORUSER.OFFICE.equals(officeOrUser)){
			String officeId = param.getOfficeId();
			Office office = officeService.get(officeId);
			//总公司的就不需要限制了
			if(!"0".equals(office.getParentId())){
				User user=new User();
				user.setOffice(office);
				param.setUsers(systemService.findUser(user));
			}
		}
		List list=null;
		switch (rangeType) {
		case StaticDefine.STATISTICS_RANGETYPE.DAY:
			list=dao.groupGetUserGrowthByDays(param);
			break;
		case StaticDefine.STATISTICS_RANGETYPE.WEEK:
			list=dao.groupGetUserGrowthByWeek(param);
			break;
		case StaticDefine.STATISTICS_RANGETYPE.MONTH:
			list=dao.groupGetUserGrowthByMonth(param);
			break;
		//默认按天
		default:
			list=dao.groupGetUserGrowthByDays(param);
			break;
		}
		return this.buildGroupData(list,param,"用户增长量统计","用户新增数量","#00E3E3");
	}
	/**
	 * @throws Exception 
	 * @throws ParseException 
	* @Title: getUserGrowthEchartsData 
	* @Description: 根据统计日期区间查询参数查询相对应日期类型的贷款申请数echarts饼图统计数据
	* @author dingGuangbiao 314667996@qq.com
	* @date 2016-10-13 下午4:11:15 
	* @param @param 查询参数
	* @return Map<String,Object>   echarts饼图所需json 
	* @throws
	 */
	public Map<String,Object> getApplyCustomPayEchartsData(TimeRangeParam param) throws Exception{
		String rangeType = param.getRangeType();
		String officeOrUser = param.getOfficeOrUser();
		//如果是按部门查询的话  需要查询该部门下面的所有用户  然后sql里面用in（userid1，userid2..）搞定
		if(StaticDefine.STATISTICS_OFFICEORUSER.OFFICE.equals(officeOrUser)){
			String officeId = param.getOfficeId();
			Office office = officeService.get(officeId);
			//总公司的就不需要限制了
			if(!"0".equals(office.getParentId())){
				User user=new User();
				user.setOffice(office);
				param.setUsers(systemService.findUser(user));
			}
		}
		List list=null;
		switch (rangeType) {
		case StaticDefine.STATISTICS_RANGETYPE.DAY:
			list=dao.groupGetApplyCustomPayByDays(param);
			break;
		case StaticDefine.STATISTICS_RANGETYPE.WEEK:
			list=dao.groupGetApplyCustomPayByWeek(param);
			break;
		case StaticDefine.STATISTICS_RANGETYPE.MONTH:
			list=dao.groupGetApplyCustomPayByMonth(param);
			break;
		//默认按天
		default:
			list=dao.groupGetApplyCustomPayByDays(param);
			break;
		}
		return this.buildGroupData(list,param,"贷款申请数统计","新申请数量","#FBA222");
	}
	/**
	 * @throws Exception 
	 * @throws ParseException 
	* @Title: getUserGrowthEchartsData 
	* @Description: 根据统计日期区间查询参数查询相对应日期类型的用户缴费总额echarts柱状图统计数据
	* @author dingGuangbiao 314667996@qq.com
	* @date 2016-10-13 下午4:11:15 
	* @param @param 查询参数
	* @return Map<String,Object>   echarts饼图所需json 
	* @throws
	 */
	public Map<String,Object> getServiceChargeEchartsData(TimeRangeParam param) throws Exception{
		String rangeType = param.getRangeType();
		String officeOrUser = param.getOfficeOrUser();
		//如果是按部门查询的话  需要查询该部门下面的所有用户  然后sql里面用in（userid1，userid2..）搞定
		if(StaticDefine.STATISTICS_OFFICEORUSER.OFFICE.equals(officeOrUser)){
			String officeId = param.getOfficeId();
			Office office = officeService.get(officeId);
			//总公司的就不需要限制了
			if(!"0".equals(office.getParentId())){
				User user=new User();
				user.setOffice(office);
				param.setUsers(systemService.findUser(user));
			}
		}
		List list=null;
		switch (rangeType) {
		case StaticDefine.STATISTICS_RANGETYPE.DAY:
			list=dao.groupGetServiceChargeByDays(param);
			break;
		case StaticDefine.STATISTICS_RANGETYPE.WEEK:
			list=dao.groupGetServiceChargeByWeek(param);
			break;
		case StaticDefine.STATISTICS_RANGETYPE.MONTH:
			list=dao.groupGetServiceChargeByMonth(param);
			break;
		//默认按天
		default:
			list=dao.groupGetServiceChargeByDays(param);
			break;
		}
		return this.buildGroupData(list,param,"用户缴费总额统计","缴费总额","#02F78E");
	}
	
	/**
	 * @throws Exception 
	 * @throws ParseException 
	* @Title: getUserGrowthEchartsData 
	* @Description: 根据统计日期区间查询参数查询相对应日期类型的用户下款总额echarts柱状图统计数据
	* @author dingGuangbiao 314667996@qq.com
	* @date 2016-10-13 下午4:11:15 
	* @param @param 查询参数
	* @return Map<String,Object>   echarts柱状图所需json 
	* @throws
	 */
	public Map<String,Object> getFinishLoanEchartsData(TimeRangeParam param) throws Exception{
		String rangeType = param.getRangeType();
		String officeOrUser = param.getOfficeOrUser();
		//如果是按部门查询的话  需要查询该部门下面的所有用户  然后sql里面用in（userid1，userid2..）搞定
		if(StaticDefine.STATISTICS_OFFICEORUSER.OFFICE.equals(officeOrUser)){
			String officeId = param.getOfficeId();
			Office office = officeService.get(officeId);
			//总公司的就不需要限制了
			if(!"0".equals(office.getParentId())){
				User user=new User();
				user.setOffice(office);
				param.setUsers(systemService.findUser(user));
			}
		}
		List list=null;
		switch (rangeType) {
		case StaticDefine.STATISTICS_RANGETYPE.DAY:
			list=dao.groupGetFinishLoanByDays(param);
			break;
		case StaticDefine.STATISTICS_RANGETYPE.WEEK:
			list=dao.groupGetFinishLoanByWeek(param);
			break;
		case StaticDefine.STATISTICS_RANGETYPE.MONTH:
			list=dao.groupGetFinishLoanByMonth(param);
			break;
		//默认按天
		default:
			list=dao.groupGetFinishLoanByDays(param);
			break;
		}
		return this.buildGroupData(list,param,"用户下款总额统计","下款总额","#2FA4E7");
	}
	private Map<String, Object> buildGroupData(List list, TimeRangeParam param,String titleText,String seriesName,String barColor) throws Exception {
		String rangeType = param.getRangeType();
		String startDates = param.getStartDate();
		String endDates = param.getEndDate();
		//从开始日期到结束日期如果都有数据的期间列表（主要为了方便和有数据的列表对比，补全没数据的天数或者周数或者月数）
		List<Date> fullInterval=new ArrayList<>();
		SimpleDateFormat fmtyyyyMMdd;
		SimpleDateFormat fmtyyyyMM;
		List<Map<String,Object>> fullData=new ArrayList<Map<String,Object>>();
		switch (rangeType) {
		case StaticDefine.STATISTICS_RANGETYPE.DAY:
			 fmtyyyyMMdd = new SimpleDateFormat("yyyyMMdd");
			fullInterval=getDateArrays(fmtyyyyMMdd.parse(startDates),fmtyyyyMMdd.parse(endDates),Calendar.DAY_OF_MONTH);
			//和有数据的列表对比，补全没数据的天数或者周数或者月数
			for (Date date : fullInterval) {
				String dayFull = fmtyyyyMMdd.format(date);
				Map<String, Object> item=new HashMap<String, Object>();
				boolean hasData=false;
				for (Object obj : list) {
					Map<String,String> dbRet=(Map<String, String>) obj;
					String  day=dbRet.get("days");
					if(dayFull.equals(day)){
						item.put(day, dbRet.get("count"));
						hasData=true;
					}
				}
				if(!hasData){
					item.put(dayFull, "0");
				}
				fullData.add(item);
			}
			break;
		case StaticDefine.STATISTICS_RANGETYPE.WEEK:
			  fmtyyyyMM = new SimpleDateFormat("yyyyMMdd");
	            Date sdate = fmtyyyyMM.parse(startDates);
	            Date edate = fmtyyyyMM.parse(endDates);
	            List<String> fullWeeks = getWeekArrays(sdate,edate);
	            for (String fullWeek : fullWeeks) {
					Map<String, Object> item=new HashMap<String, Object>();
					boolean hasData=false;
	            	for (Object obj : list) {
						Map<String,String> dbRet=(Map<String, String>) obj;
						String  week=dbRet.get("weeks");
						if(fullWeek.equals(week)){
							item.put(week, dbRet.get("count"));
							hasData=true;
						}
					}
	            	if(!hasData){
						item.put(fullWeek, "0");
					}
					fullData.add(item);
				}
			break;
		case StaticDefine.STATISTICS_RANGETYPE.MONTH:
			 fmtyyyyMM = new SimpleDateFormat("yyyyMM");  
			fullInterval=getDateArrays(fmtyyyyMM.parse(startDates),fmtyyyyMM.parse(endDates),Calendar.MONTH);
			//和有数据的列表对比，补全没数据的天数或者周数或者月数
			for (Date date : fullInterval) {
				String monthFull = fmtyyyyMM.format(date);
				Map<String, Object> item=new HashMap<String, Object>();
				boolean hasData=false;
				for (Object obj : list) {
					Map<String,String> dbRet=(Map<String, String>) obj;
					String  month=dbRet.get("months");
					if(monthFull.equals(month)){
						item.put(month, dbRet.get("count"));
						hasData=true;
					}
				}
				if(!hasData){
					item.put(monthFull, "0");
				}
				fullData.add(item);
			}
			break;
		//默认按天
		default:
			 fmtyyyyMMdd = new SimpleDateFormat("yyyyMMdd");  
			 fullInterval=getDateArrays(fmtyyyyMMdd.parse(startDates),fmtyyyyMMdd.parse(endDates),Calendar.DAY_OF_MONTH);
				//和有数据的列表对比，补全没数据的天数或者周数或者月数
				for (Date date : fullInterval) {
					String dayFull = fmtyyyyMMdd.format(date);
					Map<String, Object> item=new HashMap<String, Object>();
					boolean hasData=false;
					for (Object obj : list) {
						Map<String,String> dbRet=(Map<String, String>) obj;
						String  day=dbRet.get("days");
						if(dayFull.equals(day)){
							item.put(day, dbRet.get("count"));
							hasData=true;
						}
					}
					if(!hasData){
						item.put(dayFull, "0");
					}
					fullData.add(item);
				}
			break;
		}
		Map<String,Object> ret=new HashMap<String,Object>();
		Map<String,Object> xAxis=new HashMap<String,Object>();
	//	ret.put("series", new String[]{"10", "20", "30", "10", "50", "25", "30"});
		ret.put("xAxis", xAxis);	
		List<Object> xAxisData=new ArrayList<Object>();
		List<Object> seriesData=new ArrayList<Object>();
		xAxis.put("data", xAxisData);
		ret.put("series",seriesData );
		for (Map<String, Object> map : fullData) {
			for (String key : map.keySet()) {
				if(rangeType.equals(StaticDefine.STATISTICS_RANGETYPE.WEEK)){
					String year = key.substring(0, 4);
					String week = key.substring(4, key.length());
					xAxisData.add(year+"年第"+week+"周");
				}else if(rangeType.equals(StaticDefine.STATISTICS_RANGETYPE.MONTH)){
					String year = key.substring(0, 4);
					String month = key.substring(4, key.length());
					xAxisData.add(year+"年"+month+"月");
				}else if(rangeType.equals(StaticDefine.STATISTICS_RANGETYPE.DAY)){
					String year = key.substring(0, 4);
					String month = key.substring(4, 6);
					String day = key.substring(6, key.length());
					xAxisData.add(year+"-"+month+"-"+day);
				}else{
					xAxisData.add(key);
				}
				//金额的话 要分转为元
				if(param.getStatisticsType().equals(StaticDefine.STATISTICS_TYPE.FINISHLOAN)||param.getStatisticsType().equals(StaticDefine.STATISTICS_TYPE.SERVICECHARGE)){
					Object object = map.get(key);
					Long amout=0l;
					if(object instanceof Double){
						Double obj=(Double) object;
						amout=obj.longValue();
					}else if(object instanceof BigDecimal){
						BigDecimal obj=(BigDecimal) object;
						amout=obj.longValue() ;
						System.out.println(amout);
					}else{
						amout=Long.parseLong((String) object) ;
					}
					//seriesData.add( AmountUtils.changeF2YWithUnit(amout, "元"));
					String amountStr=AmountUtils.changeF2Y(amout);
					amountStr   =   amountStr.replace( ",", "");
					seriesData.add(amountStr);
					//seriesData.add(map.get(key));
				}else{
					seriesData.add(map.get(key));
				}
				
			}
		}
		if(seriesData.size()>15){
			ret.put("rotate", "45");	
		}
		ret.put("titleText", titleText);
		ret.put("seriesName", seriesName);
		ret.put("barColor", barColor);
		return ret;
	}
	 public static List getDateArrays(Date start, Date end, int calendarType) {
	      ArrayList ret = new ArrayList();
	      Calendar calendar = Calendar.getInstance();
	      calendar.setTime(start);
	      Date tmpDate = calendar.getTime();
	      long endTime = end.getTime();
	      while (tmpDate.before(end) || tmpDate.getTime() == endTime) {
	        ret.add(calendar.getTime());
	        calendar.add(calendarType, 1);
	        tmpDate = calendar.getTime();
	      }
	      Date[] dates = new Date[ret.size()];
	      return  Arrays.asList(ret.toArray(dates));
	    }
	 public static void main(String[] args) {
		
		 Calendar calendar = Calendar.getInstance();
	      Date start=DateUtil.StringToDate("2016-10-24", "yyyy-MM-dd");
	      calendar.setTime(start);
	      calendar.setFirstDayOfWeek(Calendar.MONDAY);
	      int startWeek = calendar.get(Calendar.WEEK_OF_YEAR);
	 }
	 public static List<String> getWeekArrays(Date start, Date end) {
		 List<String> ret = new ArrayList();
	      Calendar calendar = Calendar.getInstance();
	      calendar.setFirstDayOfWeek(Calendar.MONDAY);
	      calendar.setTime(start);
	      int startYear=calendar.get(Calendar.YEAR);
	      int startWeek = calendar.get(Calendar.WEEK_OF_YEAR);
	      
	      Calendar calendarEnd = Calendar.getInstance();
	      calendarEnd.setFirstDayOfWeek(Calendar.MONDAY);
	      calendarEnd.setTime(end);
	      int endWeek = calendarEnd.get(Calendar.WEEK_OF_YEAR);
	      if(endWeek>startWeek){
	    	  for (int i = startWeek; i <=endWeek; i++) {
	    		  if(i!=startWeek){
	    			  calendar.add(Calendar.WEEK_OF_YEAR, 1);
	    		  }
		    	  ret.add(""+calendar.get(Calendar.YEAR)+calendar.get(Calendar.WEEK_OF_YEAR)+"");
		      }  
	      }else{
	    	  //跨年了
	    	  int maxWeekNumOfYear = DateUtil.getMaxWeekNumOfYear(startYear);
	    	  for (int i = startWeek; i <=maxWeekNumOfYear; i++) {
	    		  if(i!=startWeek){
	    			  calendar.add(Calendar.WEEK_OF_YEAR, 1);
	    		  }
		    	  ret.add(""+calendar.get(Calendar.YEAR)+calendar.get(Calendar.WEEK_OF_YEAR)+"");
		      } 
	    	  calendar.setTime(end);
	    	  calendar.set(Calendar.WEEK_OF_YEAR, calendar.get(Calendar.WEEK_OF_YEAR) - 1); 
	    	  for (int i = 1; i <=endWeek; i++) {
		    	  calendar.add(Calendar.WEEK_OF_YEAR, 1);
		    	  ret.add(""+calendar.get(Calendar.YEAR)+fillZero(calendar.get(Calendar.WEEK_OF_YEAR))+"");
		      } 
	      }
	      return  ret;
	    }
	 
	  public static String fillZero(int i){
			String str="";
			if(i>0&&i<10){
				str = "0"+i;
			}else{
				str=""+i;
			}
			return str;
		}

    public Object getRefundEchartsData(TimeRangeParam param) throws Exception {
		String rangeType = param.getRangeType();
		String officeOrUser = param.getOfficeOrUser();
		//如果是按部门查询的话  需要查询该部门下面的所有用户  然后sql里面用in（userid1，userid2..）搞定
		if(StaticDefine.STATISTICS_OFFICEORUSER.OFFICE.equals(officeOrUser)){
			String officeId = param.getOfficeId();
			Office office = officeService.get(officeId);
			//总公司的就不需要限制了
			if(!"0".equals(office.getParentId())){
				User user=new User();
				user.setOffice(office);
				param.setUsers(systemService.findUser(user));
			}
		}
		List list=null;
		switch (rangeType) {
			case StaticDefine.STATISTICS_RANGETYPE.DAY:
				list=dao.groupGetRefundByDays(param);
				break;
			case StaticDefine.STATISTICS_RANGETYPE.WEEK:
				list=dao.groupGetRefundByWeek(param);
				break;
			case StaticDefine.STATISTICS_RANGETYPE.MONTH:
				list=dao.groupGetRefundByMonth(param);
				break;
			//默认按天
			default:
				list=dao.groupGetRefundByDays(param);
				break;
		}
		return this.buildGroupData(list,param,"用户退款统计","金额","#02F78E");
    }
}
